home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / c / MEMLib.lha / MEMLib / Developer / source.org / mwcontrol.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-30  |  11.0 KB  |  428 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  2. * |_o_o|\\ Copyright (c) 1989 The Software Distillery.                    *
  3. * |. o.| ||          All Rights Reserved                                  *
  4. * | .  | ||          Written by Doug Walker                               *
  5. * | o  | ||          The Software Distillery                              *
  6. * |  . |//           235 Trillingham Lane                                 *
  7. * ======             Cary, NC 27513                                       *
  8. *                    BBS:(919)-471-6436                                   *
  9. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  10.  
  11. /* This file contains the routines that must be linked in to every pgm   */
  12. /* that wants to use MemLib - MWInit, MWTerm, MWCheck, MWHold, MWPurge   */
  13.  
  14. #include "mempriv.h"
  15. #include <exec/execbase.h>
  16.  
  17. struct MWGlobal mwg;
  18.  
  19. /* Autoinit routine.  This is called by the startup code before main(). */
  20. /* The 240 is the priority of this init routine.  Don't mess with it.   */
  21. int _STI_240_MWInit(void)
  22. {
  23.    MWInit(NULL, __MWFlags, __MWLogName);
  24.    return 0;
  25. }
  26.  
  27. static void MWClose(void);
  28.  
  29. /* Initialization routine - should be called once before any memory */
  30. /* is allocated                                                     */
  31.  
  32. void MWInit(BPTR dbfh, LONG flags, char *dbnm)
  33. {
  34.  
  35.    /* Close any existing log that we opened */
  36.    if(mwg.flags & MWF_ACTIVE) MWClose();
  37.  
  38.    if(dbfh) mwg.dbfh = dbfh;
  39.    else if(dbnm) mwg.dbnm = dbnm;  /* Deferred logname */
  40.    else if(!(flags & MWF_NOLOG)) mwg.dbfh = Output();
  41.  
  42.    if(!(mwg.flags & MWF_ACTIVE))
  43.    {
  44.       mwg.lim[MWT_CHIP] = mwg.lim[MWT_FAST] = 0x7fffffff;
  45.  
  46.       mwg.task = FindTask(0L);
  47.    }
  48.  
  49.    mwg.flags = flags|MWF_ACTIVE;
  50. }
  51.  
  52. /* Termination routine.  Called by the cleanup code after exit(). */
  53. /* The 240 is the priority of this cleanup routine; don't mess with it. */
  54.  
  55. void _STD_240_MWTerm(void)
  56. {
  57.    struct MWAlc *mwa;
  58.    int msgdone = 0;
  59.  
  60.    if(!mwg.flags & MWF_ACTIVE)
  61.       return;
  62.  
  63.    MWCheck();
  64.  
  65.    /* no need to trash the mem we may be about to free for good */
  66.    mwg.flags |= MWF_NOFTRASH;
  67.    mwg.flags &= ~MWF_CHECK;
  68.  
  69.    if(!(mwg.flags & MWF_NOFREE))
  70.    {
  71.       for(mwa=mwg.first; mwa; mwa=mwa->next)
  72.       {
  73.          if(!(mwa->flags & (MWI_MALLOC|MWI_VEC)))
  74.          {
  75.             if(!msgdone)
  76.             {
  77.                MWPrintf("%sMemWatch ERROR: The following "
  78.                         "allocations were not freed:\n",MW_NEWLINE);
  79.                msgdone = 1;
  80.             }
  81.             MWPrintAlc(mwa);
  82.          }
  83.       }
  84.       while(mwg.first)
  85.          MWFreeMem(mwg.first->memory, mwg.first->size, MWI_ANY, "MWTERM", 0);
  86.    }
  87.    MWPurge();  /* Really free all mem on the 'free' chain */
  88.  
  89.    MWClose();
  90.  
  91.    memset((char *)&mwg, 0, sizeof(struct MWGlobal));
  92. }
  93.  
  94. /* For compatibility with previous versions */
  95. void MWTerm(void)
  96. {
  97.    _STD_240_MWTerm();
  98. }
  99.  
  100. #define V37 ((*(struct ExecBase **)4)->LibNode.lib_Version >= 36)
  101.  
  102. static void MWClose(void)
  103. {
  104.    char tmp[2];
  105.  
  106.    if(mwg.dbnm && mwg.dbfh)
  107.    {
  108.       if(!V37)  // If V37, they will be using /AUTO/CLOSE/WAIT
  109.       {
  110.          MWPrintf("Hit RETURN to continue: ");
  111.          Read(mwg.dbfh, tmp, 1);
  112.       }
  113.       Close(mwg.dbfh);
  114.    }
  115.    mwg.dbfh = NULL;
  116. }
  117.  
  118. void MWLimit(LONG chiplim, LONG fastlim)
  119. {
  120.    mwg.lim[MWT_CHIP] = chiplim;
  121.    mwg.lim[MWT_FAST] = fastlim;
  122. }
  123.  
  124. int MWCheckA(struct MWAlc *mwa)
  125. {
  126.    int header, trailer;
  127.    char trash[2*MW_TRAILLEN+1];
  128.    int i, j;
  129.    char *mem;
  130.    static const char hexchars[] = "0123456789ABCDEF";
  131.  
  132.    if(mwa->internal & MWI_REPORTED)
  133.       return 0;
  134.  
  135.    if(header=memcmp((char *)&mwa->header, MWHEADSTR, MW_HEADLEN))
  136.       MWPrintf("%sMemWatch ERROR: Header trashed\n",MW_NEWLINE);
  137.  
  138.    if(trailer=memcmp(mwa->memory+mwa->size, MWTRAILSTR, MW_TRAILLEN))
  139.    {
  140.       mem = mwa->memory + mwa->size;
  141.       for(i=j=0; i<MW_TRAILLEN; i++)
  142.       {
  143.          trash[j++] = hexchars[(mem[i]&0xf0)>>4];
  144.          trash[j++] = hexchars[mem[i]&0xf];
  145.       }
  146.       trash[j] = 0;
  147.       MWPrintf("%sMemWatch ERROR: Trailer trashed, data 0x%s\n", MW_NEWLINE, trash);
  148.    }
  149.  
  150.    if(header || trailer)
  151.    {
  152.       mwa->internal |= MWI_REPORTED;
  153.       MWPrintAlc(mwa);
  154.       return(1);
  155.    }
  156.  
  157.    return(0);
  158. }
  159.  
  160. /* Validity check routine - checks all known allocations for overwrites */
  161. /* Called from every alloc and free routine, plus when specifically     */
  162. /* invoked                                                              */
  163.  
  164. void MWCheck(void)
  165. {
  166.    struct MWAlc *mwa;
  167.    char *tmpchar;
  168.    int error, tmpint;
  169.  
  170.    error = 0;
  171.    for(mwa=mwg.first; mwa; mwa=mwa->next)
  172.    {
  173.       if( (mwa->internal & MWI_REPMASK) == MWI_REPORTED) continue;
  174.  
  175.       error = MWCheckA(mwa);
  176.    }
  177.  
  178.    for(mwa=mwg.freed; mwa; mwa=mwa->next)
  179.    {
  180.       if( (mwa->internal & MWI_REPMASK) == MWI_REPORTED) continue;
  181.  
  182.       for(tmpint=0, tmpchar=mwa->memory;
  183.           tmpint<mwa->size;
  184.           tmpint++, tmpchar++)
  185.       {
  186.          if(*tmpchar != MWFTRASH)
  187.          {
  188.             mwa->internal |= MWI_REPORTED;
  189.             error = 1;
  190.             MWPrintf("%sMemWatch ERROR: Freed memory modified\n",MW_NEWLINE);
  191.             MWPrintAlc(mwa);
  192.             break;
  193.          }
  194.       }
  195.    }
  196.  
  197.    if(error) MWHold();
  198. }
  199.  
  200. void MWHold(void)
  201. {
  202.    struct MWAlc *mwa;
  203.  
  204.    mwg.flags &= ~MWF_ERROR;
  205.  
  206.    /* We're attempting to go on, make all the sentinels correct */
  207.    for(mwa=mwg.first; mwa; mwa=mwa->next)
  208.    {
  209.       mwa->internal &= ~MWI_REPMASK;
  210.       memcpy(mwa->header, MWHEADSTR, MW_HEADLEN);
  211.       memcpy((mwa->memory + mwa->size), MWTRAILSTR, MW_TRAILLEN);
  212.    }
  213.  
  214.    for(mwa=mwg.freed; mwa; mwa=mwa->next)
  215.    {
  216.       mwa->internal &= ~MWI_REPMASK;
  217.       memset(mwa->memory, MWFTRASH, mwa->size);
  218.    }
  219. }
  220.  
  221. /* MWPurge really frees all memory placed on the 'freed' chain by */
  222. /* FreeMem() or free()                                            */
  223.  
  224. void MWPurge(void)
  225. {
  226.    struct MWAlc *cur, *next;
  227.  
  228.    for(cur=mwg.freed; cur; cur=next)
  229.    {
  230.       next = cur->next;
  231.       FreeMem(cur, cur->size + sizeof(struct MWAlc));
  232.    }
  233.    mwg.freed = NULL;
  234. }
  235.  
  236. void MWPrintf(char *ctl, ...)
  237. {
  238.    static char buffer[256];
  239.    va_list args;
  240.  
  241.    va_start(args, ctl);
  242.  
  243.    /* Note: The weird string constant is actually CODE that will */
  244.    /* be called by RawDoFmt.                                     */
  245.    RawDoFmt(ctl, args, (void (*))"\x16\xc0\x4e\x75", buffer);
  246.  
  247.    va_end(args);
  248.  
  249. /* If you don't have Commodore's debug.lib, KPutStr will come up undefined. */
  250. /* Edit mempriv.h and change the #define for USEDEBUGLIB to 0 in this case. */
  251. #if USEDEBUGLIB
  252.    if(mwg.flags & MWF_SERIAL) KPutStr(buffer);
  253.    else
  254. #endif
  255.    {
  256.       if(!mwg.dbfh && mwg.dbnm) mwg.dbfh = Open(mwg.dbnm, MODE_NEWFILE);
  257.       if(mwg.dbfh) Write(mwg.dbfh, buffer, strlen(buffer));
  258.    }
  259. }
  260.  
  261. void *MWAllocMem(long size, long flags, long internal, char *file, long line)
  262. {
  263.    struct MWAlc *hd;
  264.    char *tmpchar;
  265.    int memtype;
  266.  
  267.    if(!(mwg.flags & MWF_ACTIVE)) return(NULL);
  268.  
  269.    /* Force warning for malloc'd memory not freed if requested */
  270.    if(mwg.flags & MWF_MALLOCWRN) internal &= ~MWI_MALLOC;
  271.  
  272.    if(mwg.flags & MWF_CHECK) MWCheck();
  273.  
  274.    if(size <= 0)
  275.    {
  276.       MWPrintf("%sMemWatch ERROR: Bad %s() length %ld from line %ld file \"%s\"\n",
  277.          MW_NEWLINE, ALCFAMILY(internal), size, line, file);
  278.       return(NULL);
  279.    }
  280.  
  281.    memtype = (flags & MEMF_CHIP ? MWT_CHIP : MWT_FAST);
  282.    if(mwg.sum[memtype] + size > mwg.lim[memtype])
  283.    {
  284.       /* Over the limit, fail it */
  285.       MWPrintf("MemWatch: %s memory allocation exceeds MWLimit amount\n",
  286.          memtype == MWT_CHIP ? "CHIP" : "FAST");
  287.       return(NULL);
  288.    }
  289.  
  290.    while(!(tmpchar = (char *)AllocMem(sizeof(struct MWAlc)+size, flags)))
  291.    {
  292.       if(mwg.freed) MWPurge();
  293.       else return(NULL);
  294.    }
  295.  
  296.    hd = (struct MWAlc *)tmpchar;
  297.    hd->size = size;
  298.    hd->flags = flags;
  299.    hd->internal = internal;
  300.    hd->file = file;
  301.    hd->line = line;
  302.    hd->ffile = NULL;
  303.    hd->fline = 0;
  304.    memcpy(hd->header, MWHEADSTR, MW_HEADLEN);
  305.    memcpy(hd->memory+size, MWTRAILSTR, MW_TRAILLEN);
  306.  
  307.    if(!(flags & MEMF_CLEAR) && !(mwg.flags & MWF_NOATRASH))
  308.       memset(hd->memory, MWATRASH, size);   /* Trash the memory */
  309.  
  310.    hd->next = mwg.first;
  311.    mwg.first = hd;
  312.  
  313.    if((mwg.sum[memtype] += size) > mwg.max[memtype])
  314.       mwg.max[memtype] = mwg.sum[memtype];
  315.    ++(mwg.num[memtype]);
  316.  
  317.    return((char *)hd->memory);
  318. }
  319.  
  320. void MWFreeMem(void *mem, long size, long internal,
  321.                char *file, long line)
  322. {
  323.    struct MWAlc *mwa, *prev;
  324.    int memtype;
  325.    int error = 0;
  326.  
  327.    if(!(mwg.flags & MWF_ACTIVE)) return;
  328.    if(mwg.flags & MWF_CHECK) MWCheck();
  329.  
  330.    for(prev = NULL, mwa = mwg.first;
  331.        mwa && mwa->memory != mem;
  332.        prev = mwa, mwa = mwa->next);
  333.  
  334.    if(!mwa)
  335.    {
  336.       for(mwa=mwg.freed; mwa && mwa->memory != mem; mwa=mwa->next);
  337.       if(mwa)
  338.       {
  339.          MWPrintf("%sMemWatch ERROR: Memory freed twice line %ld file \"%s\"\n", MW_NEWLINE,
  340.             line, file);
  341.          MWPrintAlc(mwa);
  342.       }
  343.       MWPrintf("%sMemWatch ERROR: %s() called on invalid memory\n"\
  344.                   "addr 0x%08lx length %ld line %ld file \"%s\"\n", MW_NEWLINE,
  345.             FREFAMILY(internal), mem, size, line, file);
  346.       error = 1;
  347.    }
  348.    else if(!(internal & (MWI_MALLOC|MWI_VEC)) && mwa->size != size)
  349.    {
  350.       MWPrintf("%sMemWatch ERROR: Incorrect %s() length %ld line %ld file \"%s\"\n", MW_NEWLINE,
  351.          FREFAMILY(internal), size, line, file);
  352.       MWPrintAlc(mwa);
  353.       error = 2;
  354.    }
  355.    else if(internal != MWI_ANY && (internal & mwa->internal) != internal)
  356.    {
  357.       MWPrintf("%sMemWatch ERROR: %s() mem freed with %s(), line %ld file \"%s\"\n", MW_NEWLINE,
  358.          ALCFAMILY(mwa->internal), FREFAMILY(internal), line, file);
  359.       MWPrintAlc(mwa);
  360.    }
  361.    else if(MWCheckA(mwa))
  362.      error = 2;
  363.  
  364.    if(error)
  365.    {
  366.       MWHold();
  367.       if(error == 1) return;
  368.    }
  369.  
  370.    memtype = (mwa->flags & MEMF_CHIP ? MWT_CHIP : MWT_FAST);
  371.    mwg.sum[memtype] -= mwa->size;
  372.    --mwg.num[memtype];
  373.  
  374.    if(prev) prev->next = mwa->next;
  375.    else     mwg.first = mwa->next;
  376.  
  377.    if(!(mwg.flags & MWF_NOFTRASH))
  378.       memset(mwa->memory, MWFTRASH, mwa->size);  /* Trash it */
  379.  
  380.    if(mwg.flags & MWF_NOFKEEP)
  381.      FreeMem((char *)mwa, mwa->size + sizeof(struct MWAlc));
  382.    else
  383.    {
  384.       mwa->next = mwg.freed;
  385.       mwg.freed = mwa;
  386.       mwa->ffile = file;
  387.       mwa->fline = line;
  388.    }
  389. }
  390.  
  391. void *MWrealloc(void *mem, long size, char *file, long line)
  392. {
  393.    void *new;
  394.    struct MWAlc *mwa;
  395.  
  396.    if(!(new = MWAllocMem(size, 0, MWI_MALLOC, file, line)))
  397.       return(NULL);
  398.  
  399.    if(mem)
  400.    {
  401.       for(mwa = mwg.first;
  402.           mwa && mwa->memory != mem;
  403.           mwa = mwa->next);
  404.  
  405.       if(mwa == NULL)
  406.       {
  407.          MWPrintf("%sMemWatch ERROR: bad memory passed to realloc\n",MW_NEWLINE);
  408.          MWPrintf("%sPointer is 0x%08lx, called from line %ld file \"%s\"\n", MW_NEWLINE,
  409.             line, file);
  410.       }
  411.       else if(!(mwa->internal & MWI_MALLOC))
  412.       {
  413.          MWPrintf("%sMemwatch ERROR: %s() memory passed to realloc()\n", MW_NEWLINE,
  414.             ALCFAMILY(mwa->internal));
  415.          MWPrintf("Passed from line %ld file \"%s\"\n", line, file);
  416.          MWPrintAlc(mwa);
  417.       }
  418.       else if(mwa->size < size)
  419.          size = mwa->size;
  420.  
  421.       memcpy(new, mem, size);
  422.  
  423.       if(mwa) MWFreeMem(mem, -1, MWI_MALLOC, file, line);
  424.    }
  425.  
  426.    return(new);
  427. }
  428.